package com.zxl.register.server.event;

import com.zxl.register.base.Event;
import com.zxl.register.base.Result;
import com.zxl.register.server.command.CommandHandler;
import com.zxl.register.server.core.ServiceRegistCore;
import com.zxl.register.server.socket.SocketManager;
import org.reflections.Reflections;

import java.nio.channels.AsynchronousSocketChannel;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 事件处理
 */
public class EventProcess {

    private static Thread processThread=null;

    private static Map<String,CommandHandler> allHandler=new HashMap<>();

    public EventProcess(){
        Reflections reflections = new Reflections("com.zxl.register.server.command");
        Set<Class<? extends CommandHandler>> allCommandHandler=reflections.getSubTypesOf(CommandHandler.class);
        allCommandHandler.stream().forEach(e->{
            CommandHandler handler = null;
            try {
                handler = e.newInstance();
                allHandler.put(handler.getKey(),handler);
            } catch (Exception ex) {
                ex.printStackTrace();
                System.err.println(" 初始化 EventProcess 发生异常");
                System.exit(1);
            }
        });

        processThread  =new Thread(new Runnable() {
            @Override
            public void run() {
                process();
            }
        });
        processThread.start();

    }

    private void process(){
        System.out.println(" event process started ! -0-  !   ");
        System.out.println(Thread.currentThread().getName()+" is  process thread name.");
        while(true ) {
            if (EventPool.needProcess()) {
                handle(EventPool.poll());
            }
        }
    }


    private void handle(Event event){
        Result processResult=null;
        AsynchronousSocketChannel socket  = event.getInstance().getSocketChannel();

        try {
            processResult=allHandler.get(event.getType()).handle(event);
        }catch (Throwable throwable){
            throwable.printStackTrace();
            System.err.println("处理event发生异常！ msg : "+event.toString());
            return;
        }

        SocketManager.send(processResult,socket);

        // todo: 判断是否业务处理时间过长
        if(System.currentTimeMillis() > event.getReceivedTime()+5000){
            System.err.println(" 处理 event 超时! event : "+event);
        }
    }



    public static void checkHeartBeat() {
        long start=System.currentTimeMillis();
        if(processThread==null){
            return;
        }
        try {
            processThread.wait();
            System.out.println(" start checkHeartBeat process -----------------  ");
            // pause all process
            if(ServiceRegistCore.updateInstanceByCheckHeartBeat()){
                System.out.println(" checkHeartBeat process success ! ! !  spend time (millsecend): "+(System.currentTimeMillis()-start));
                return;
            }
            System.out.println(" checkHeartBeat process failed ! ! !  spend time (millsecend): "+(System.currentTimeMillis()-start));
        }catch (Exception e){
            System.err.println(" !!! checkHeartBeat occur exception !!! spend time (millsecend): "+(System.currentTimeMillis()-start));
        }finally {
            processThread.notify();
        }
    }
}
